From 47c4bf5be0e90c419c63638380c99cd40607b446 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Timm=20B=C3=A4der?= Date: Fri, 1 Dec 2017 08:30:11 +0100 Subject: [PATCH] gl renderer: Implement unblurred outset shadows --- gsk/gl/gskglrenderer.c | 48 +++++++++++++++++++++++- gsk/gl/gskglrenderopsprivate.h | 24 ++++++++++-- gsk/meson.build | 1 + gsk/resources/glsl/outset_shadow.fs.glsl | 27 +++++++++++++ 4 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 gsk/resources/glsl/outset_shadow.fs.glsl diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 948e4eb1f6..325ee83655 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -170,6 +170,7 @@ struct _GskGLRenderer Program linear_gradient_program; Program blur_program; Program inset_shadow_program; + Program outset_shadow_program; }; }; @@ -272,6 +273,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self, { "linear gradient", "blit.vs.glsl", "linear_gradient.fs.glsl" }, { "blur", "blit.vs.glsl", "blur.fs.glsl" }, { "inset shadow", "blit.vs.glsl", "inset_shadow.fs.glsl" }, + { "outset shadow", "blit.vs.glsl", "outset_shadow.fs.glsl" }, }; builder = gsk_shader_builder_new (); @@ -374,6 +376,14 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self, INIT_PROGRAM_UNIFORM_LOCATION2 (inset_shadow, corner_widths); INIT_PROGRAM_UNIFORM_LOCATION2 (inset_shadow, corner_heights); + /* outset shadow */ + INIT_PROGRAM_UNIFORM_LOCATION2 (outset_shadow, color); + INIT_PROGRAM_UNIFORM_LOCATION2 (outset_shadow, spread); + INIT_PROGRAM_UNIFORM_LOCATION2 (outset_shadow, offset); + INIT_PROGRAM_UNIFORM_LOCATION2 (outset_shadow, outline); + INIT_PROGRAM_UNIFORM_LOCATION2 (outset_shadow, corner_widths); + INIT_PROGRAM_UNIFORM_LOCATION2 (outset_shadow, corner_heights); + g_object_unref (builder); return TRUE; } @@ -1012,12 +1022,36 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self, } break; + case GSK_OUTSET_SHADOW_NODE: + { + RenderOp op; + + /* TODO: Implement blurred outset shadows as well */ + if (gsk_outset_shadow_node_get_blur_radius (node) > 0) + goto do_default; + + op.op = OP_CHANGE_OUTSET_SHADOW; + rgba_to_float (gsk_outset_shadow_node_peek_color (node), op.outset_shadow.color); + rounded_rect_to_floats (gsk_outset_shadow_node_peek_outline (node), + op.outset_shadow.outline, + op.outset_shadow.corner_widths, + op.outset_shadow.corner_heights); + op.outset_shadow.radius = gsk_outset_shadow_node_get_blur_radius (node); + op.outset_shadow.spread = gsk_outset_shadow_node_get_spread (node); + op.outset_shadow.offset[0] = gsk_outset_shadow_node_get_dx (node); + op.outset_shadow.offset[1] = -gsk_outset_shadow_node_get_dy (node); + + ops_set_program (builder, &self->outset_shadow_program); + ops_add (builder, &op); + ops_draw (builder, vertex_data); + } + break; + do_default: case GSK_REPEATING_LINEAR_GRADIENT_NODE: - case GSK_BORDER_NODE: - case GSK_OUTSET_SHADOW_NODE: case GSK_SHADOW_NODE: + case GSK_BORDER_NODE: case GSK_CROSS_FADE_NODE: case GSK_BLEND_NODE: case GSK_REPEAT_NODE: @@ -1323,6 +1357,16 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self, glUniform4fv (program->inset_shadow.corner_heights_location, 1, op->inset_shadow.corner_heights); break; + case OP_CHANGE_OUTSET_SHADOW: + g_assert (program == &self->outset_shadow_program); + glUniform4fv (program->outset_shadow.color_location, 1, op->outset_shadow.color); + glUniform2fv (program->outset_shadow.offset_location, 1, op->outset_shadow.offset); + glUniform1f (program->outset_shadow.spread_location, op->outset_shadow.spread); + glUniform4fv (program->outset_shadow.outline_location, 1, op->outset_shadow.outline); + glUniform4fv (program->outset_shadow.corner_widths_location, 1, op->outset_shadow.corner_widths); + glUniform4fv (program->outset_shadow.corner_heights_location, 1, op->outset_shadow.corner_heights); + break; + case OP_DRAW: OP_PRINT (" -> draw %ld, size %ld and program %s\n", op->draw.vao_offset, op->draw.vao_size, program->name); diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h index 44c3e211db..ec9bc944f6 100644 --- a/gsk/gl/gskglrenderopsprivate.h +++ b/gsk/gl/gskglrenderopsprivate.h @@ -10,7 +10,7 @@ #include "gskglrendererprivate.h" #define GL_N_VERTICES 6 -#define GL_N_PROGRAMS 8 +#define GL_N_PROGRAMS 9 enum { OP_NONE, @@ -28,8 +28,9 @@ enum { OP_CHANGE_COLOR_MATRIX = 12, OP_CHANGE_BLUR = 13, OP_CHANGE_INSET_SHADOW = 14, - OP_CLEAR = 15, - OP_DRAW = 16, + OP_CHANGE_OUTSET_SHADOW = 15, + OP_CLEAR = 16, + OP_DRAW = 17, }; typedef struct @@ -81,6 +82,14 @@ typedef struct int corner_widths_location; int corner_heights_location; } inset_shadow; + struct { + int color_location; + int spread_location; + int offset_location; + int outline_location; + int corner_widths_location; + int corner_heights_location; + } outset_shadow; }; } Program; @@ -128,6 +137,15 @@ typedef struct float offset[2]; float color[4]; } inset_shadow; + struct { + float outline[4]; + float corner_widths[4]; + float corner_heights[4]; + float radius; + float spread; + float offset[2]; + float color[4]; + } outset_shadow; }; } RenderOp; diff --git a/gsk/meson.build b/gsk/meson.build index 01bbd32b40..f05cb343e0 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -10,6 +10,7 @@ gsk_private_source_shaders = [ 'resources/glsl/blur.vs.glsl', 'resources/glsl/blur.fs.glsl', 'resources/glsl/inset_shadow.fs.glsl', + 'resources/glsl/outset_shadow.fs.glsl', 'resources/glsl/es2_common.fs.glsl', 'resources/glsl/es2_common.vs.glsl', 'resources/glsl/gl3_common.fs.glsl', diff --git a/gsk/resources/glsl/outset_shadow.fs.glsl b/gsk/resources/glsl/outset_shadow.fs.glsl new file mode 100644 index 0000000000..c927172d36 --- /dev/null +++ b/gsk/resources/glsl/outset_shadow.fs.glsl @@ -0,0 +1,27 @@ +uniform float u_spread; +uniform float u_blur_radius; +uniform vec4 u_color; +uniform vec2 u_offset; +uniform vec4 u_outline; +uniform vec4 u_corner_widths; +uniform vec4 u_corner_heights; + + +void main() { + vec4 f = gl_FragCoord; + + f.x += u_viewport.x; + f.y = (u_viewport.y + u_viewport.w) - f.y; + + RoundedRect outline = RoundedRect(vec4(u_outline.xy, u_outline.xy + u_outline.zw), + u_corner_widths, u_corner_heights); + RoundedRect outside = rounded_rect_shrink(outline, vec4(- u_spread)); + + + vec2 offset = vec2(u_offset.x, - u_offset.y); + vec4 color = vec4(u_color.rgb * u_color.a, u_color.a); + color = color * clamp (rounded_rect_coverage (outside, f.xy - offset) - + rounded_rect_coverage (outline, f.xy), + 0.0, 1.0); + setOutputColor(color); +} -- 2.30.2